package com.tang.gulimall.search.thread;

import lombok.SneakyThrows;

import java.security.PublicKey;
import java.util.concurrent.*;

public class ThreadTest {
    public static final ExecutorService executorService = new ThreadPoolExecutor(5, 200,
            20, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200),
            Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {


       /* ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 200, 20, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        threadPoolExecutor.execute(() -> {
            System.out.println("哈哈");
        });*/

      /*  System.out.println("main.....start");
        CompletableFuture<Void> future = CompletableFuture.runAsync(new Runnable() {
            @Override
            public void run() {
                System.out.println("开始!");
                int i = 10/2;
                System.out.println("执行结束!");
            }
        }, executorService);
        System.out.println("main.....end");*/

    /*    System.out.println("main.....start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("开始!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int i = 10 / 2;
            System.out.println("执行结束!");
            return 10;
        }, executorService);

//        Integer integer = future.get();

        System.out.println("main.....end");
*/
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("开始!");
            int i = 10 / 0;
            System.out.println("执行结束!");
            return 10;
        }, executorService).whenComplete((r,e)->{
            System.out.println("异步任务完成了,结果是"+r+";异常是:"+e);
        }).exceptionally(throwable -> {
            return 100;
        });*/

       /* CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("开始!");
            // int i = 10 / 0;
            System.out.println("执行结束!");
            return 10;
        }, executorService).handle((r,e)->{
            if (r!=null){
                //有结果
                return r*2;
            }
            if (e!=null){
                return 10;
            }
            return r*2;
        });
        Integer integer = future.get();
        System.out.println(integer);
        System.out.println("主方法!");*/




        /*System.out.println("主线程 开始!");
        // new Thread01().start();
        // new Thread(new Runnable01()).start();
        FutureTask<Integer> futureTask = new FutureTask(new Callable01());
        new Thread(futureTask).start();
        Integer integer = futureTask.get();

        System.out.println("主线程"+integer);*/
        /*for (int i = 0; i < 100; i++) {
            executorService.execute(new Runnable01());
        }


        System.out.println("主线程结束!");*/

       /* System.out.println("main.....start");
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 10 / 4;
            System.out.println("运行结果:" + i);
            return i;
        }, executorService).thenApplyAsync((result -> {
            System.out.println("上个线程返回结果:" + result+"====>当前线程:"+Thread.currentThread().getName());
            return result;
        }), executorService);
        System.out.println("main.....end");*/

       /* CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 10 / 4;
            System.out.println("运行结果:" + i);
            return i;
        }, executorService).thenRun(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
        });*/


        //有返回值异步任务
        /*CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getName());
            int i = 10 / 4;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("运行结果:" + i);
            return i;
        }, executorService);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("hello");
            return "hello";
        }, executorService);*/

        //等待上面两个异步任务结束执行下面这个异步任务(不能获取上面的结果以及没有返回值)
       /* future01.runAfterBothAsync(future02,()->{
            System.out.println("任务3开始");
        },executorService);*/

        //等待上面两个异步任务结束执行下面这个异步任务(能获取上面的结果但是没有返回值)
       /* future01.thenAcceptBothAsync(future02,(f1,f2)->{
            System.out.println("任务3开始:返回值1:"+f1+" 返回值2:"+f2);
        },executorService);*/


        //等待上面两个异步任务结束执行下面这个异步任务(能获取上面的结果并且有返回值)
      /*  CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            System.out.println("任务3开始:返回值1:" + f1 + " 返回值2:" + f2);
            return f1 + ":" + f2 + "";
        }, executorService);

        System.out.println("返回值:"+future.get());*/

        //等待上面两个其中的一个异步任务结束执行下面这个异步任务(不能获取上面的结果以及没有返回值)
        /*future01.runAfterEitherAsync(future02,()->{
            System.out.println("任务3开始");
        },executorService);*/

        //等待上面两个其中一个异步任务结束执行下面这个异步任务(能获取上面的结果但是没有返回值) 前面两个异步任务返回值类型必须为同一类型
        /*future01.acceptEitherAsync(future02,(obj)->{
            System.out.println("任务3开始:返回值:"+obj);
        },executorService);*/


        //等待上面两个其中一个异步任务结束执行下面这个异步任务(能获取上面的结果并且有返回值) 前面两个异步任务返回值类型必须为同一类型
        /*CompletableFuture<String> future = future01.applyToEitherAsync(future02, (obj) -> {
            System.out.println("任务3开始:返回值1:" +obj);
            return obj+"嘻嘻";
        }, executorService);

        System.out.println("结果:"+future.get());*/


        /*CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("获取商品图片");
            return "获取商品图片";
        }, executorService);

        CompletableFuture<String> futureDetail = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("获取商品详情");
            return "获取商品详情";
        }, executorService);

        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("获取商品属性");
            return "获取商品属性";
        }, executorService);


        //等待上述所有任务结束
      *//*  CompletableFuture<Void> future = CompletableFuture.allOf(futureImg, futureDetail, futureAttr);
        future.get();*//*

        //等待上述任务其中一个执行完成就结束
        CompletableFuture<Object> future = CompletableFuture.anyOf(futureImg, futureDetail, futureAttr);
        //拿到最先执行完的任务返回值
        Object o = future.get();
        System.out.println("main线程结束:"+o);*/


    }


    /**
     * 开启线程第一种方式
     */
    public static class Thread01 extends Thread {
        @SneakyThrows
        @Override
        public void run() {
            System.out.println("继承thread类 开启线程");

            int i = 10 / 2;

            System.out.println("执行结束!");
        }
    }

    /**
     * 开启线程第二种方式
     */
    public static class Runnable01 implements Runnable {

        @SneakyThrows
        @Override
        public void run() {
            System.out.println("实现Runnable接口 开启线程" + Thread.currentThread().getId());
            Thread.sleep(5000);
            int i = 10 / 2;

            System.out.println("执行结束!");
        }
    }

    /**
     * 开启线程第三种方式
     */
    public static class Callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("实现callable接口 开启线程");

            int i = 10 / 2;

            System.out.println("执行结束!");

            return -1;
        }
    }
}
